import base64
import datetime
import io
import os

import requests
from PIL import Image
from flask import Blueprint, request, jsonify, current_app
from flask_jwt_extended import jwt_required, get_jwt_identity

from app.models.system import Banner, Notice, Article, Feedback, PopupNotice
from app.models.user import ShareRelation, User, RewardRecord
from app.core.extensions import db
from sqlalchemy import func
import time
import random
from app.services.system_service import upload_file_to_cos
from app.services.auth import token_required

system_bp = Blueprint('system', __name__)


@system_bp.route('/banners', methods=['GET'])
def get_banners():
    try:
        banners = Banner.query.filter_by(status=1).order_by(Banner.sort.asc()).all()
        return jsonify({
            "code": 1,
            "msg": "获取成功",
            "data": {
                "list": [banner.to_dict() for banner in banners]
            }
        })
    except Exception as e:
        current_app.logger.error(f"获取轮播图错误: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


@system_bp.route('/banners/<int:banner_id>', methods=['PUT'])
def update_banner(banner_id):
    data = request.get_json()
    if not data:
        return jsonify({"code": 0, "msg": "请求数据不能为空"}), 400

    banner = Banner.query.get(banner_id)
    if not banner:
        return jsonify({"code": 0, "msg": "未找到对应的Banner"}), 404

    try:
        banner.hex = data.get("hex", banner.hex)

        db.session.commit()

        return jsonify({
            "code": 1,
            "msg": "更新成功",
            "data": banner.to_dict()
        })
    except Exception as e:
        db.session.rollback()
        return jsonify({"code": 0, "msg": f"更新失败：{str(e)}"}), 500


@system_bp.route('/notices', methods=['GET'])
def get_notices():
    try:
        from flask import g
        # 对于公开接口，跳过租户检查
        g.skip_tenant_check = True
        notices = Notice.query.filter_by(status=1).order_by(Notice.sort.asc()).all()

        return jsonify({
            "code": 1,
            "msg": "获取成功",
            "data": {
                "list": [notice.to_dict() for notice in notices]
            }
        })

    except Exception as e:
        current_app.logger.error(f"获取公告错误: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


@system_bp.route('/articles', methods=['GET'])
def get_articles():
    try:
        articles = Article.query.filter_by(status=1).order_by(
            Article.is_top.desc(),
            Article.sort_number.asc(),
            Article.update_time.desc()
        ).all()

        return jsonify({
            "code": 1,
            "msg": "获取成功",
            "data": {
                "list": [article.to_dict() for article in articles]
            }
        })

    except Exception as e:
        current_app.logger.error(f"获取文章列表错误: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


@system_bp.route('/share/bind', methods=['POST'])
def bind_share():
    data = request.json
    sharer_id = float(data.get('sharerId'))
    user_id = float(data.get('userId'))

    if not sharer_id or not user_id:
        return jsonify({'code': 400, 'msg': '参数缺失'})

    if sharer_id == user_id:
        return jsonify({'code': 200, 'msg': '不能绑定自己'})

    # 检查是否已绑定
    existing = ShareRelation.query.filter_by(invitee_id=user_id).first()
    if existing:
        return jsonify({'code': 200, 'msg': '已绑定过推荐人'})

    try:
        # 绑定关系
        relation = ShareRelation(sharer_id=sharer_id, invitee_id=user_id)
        db.session.add(relation)

        # 推荐人使用次数 +2
        sharer = User.query.filter_by(user_id=sharer_id).first()
        if sharer:
            sharer.usage_count = sharer.usage_count + 2
        handle_invite_reward(sharer_id)
        db.session.commit()
        return jsonify({'code': 1, 'msg': '绑定成功'})

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"绑定推荐关系错误: {str(e)}")
        return jsonify({'code': 500, 'msg': '服务器错误', 'error': str(e)})


def handle_invite_reward(user_id):
    # 统计当前邀请人数
    total_invites = ShareRelation.query.filter_by(sharer_id=user_id).count()

    # 计算奖励阶段：比如 5、10、15...
    reward_stage = (total_invites // 5) * 5
    if reward_stage < 5:
        return  # 不够5人，直接返回

    # 检查是否已发放该阶段奖励
    existing = RewardRecord.query.filter_by(user_id=user_id, reward_type='invite', reward_stage=reward_stage).first()
    if existing:
        return  # 已经发过奖励了，不重复发

    # 发奖励
    user = User.query.filter_by(user_id=user_id).first()
    user.usage_count += 20

    # 写入奖励记录
    reward = RewardRecord(
        user_id=user_id,
        reward_type='invite',
        reward_stage=reward_stage,
        reward_count=20
    )
    db.session.add(reward)
    db.session.commit()


@system_bp.route('/share/count', methods=['GET'])
def share_count():
    sharer_id = request.args.get('sharerId')

    if not sharer_id:
        return jsonify({'code': 400, 'msg': '参数缺失'})

    try:
        count = ShareRelation.query.filter_by(sharer_id=sharer_id).count()
        return jsonify({'code': 1, 'msg': '查询成功', 'data': {'count': count}})
    except Exception as e:
        current_app.logger.error(f"查询分享数量错误: {str(e)}")
        return jsonify({'code': 500, 'msg': '服务器异常', 'error': str(e)})


@system_bp.route('/getuserTop', methods=['GET'])
def get_top_sharers():
    try:
        # 第一步：统计 sharer_id 出现次数（就是邀请人数）
        sharer_counts = (
            db.session.query(
                ShareRelation.sharer_id,
                func.count(ShareRelation.invitee_id).label('invite_count')
            )
            .group_by(ShareRelation.sharer_id)
            .order_by(func.count(ShareRelation.invitee_id).desc())
            .limit(30)
            .all()
        )

        if not sharer_counts:
            return jsonify({
                "code": 1,
                "msg": "暂无数据",
                "data": {
                    "list": []
                }
            })

        # 第二步：提取出 sharer_id 列表
        sharer_ids = [item.sharer_id for item in sharer_counts]

        # 第三步：根据 sharer_id 查询用户信息
        users = User.query.filter(User.user_id.in_(sharer_ids)).all()
        user_dict = {user.user_id: user for user in users}  # 方便通过 id 找用户信息

        # 第四步：组装返回数据
        result = []
        for idx, item in enumerate(sharer_counts, start=1):
            user = user_dict.get(item.sharer_id)
            if user:
                result.append({
                    "rank": idx,  # 排名
                    "id": user.user_id,
                    "nickname": user.nick_name if hasattr(user, 'nick_name') else '',
                    "avatar_url": user.avatar_url if hasattr(user, 'avatar_url') else '',
                    "amount": item.invite_count  # 邀请人数
                })

        return jsonify({
            "code": 1,
            "msg": "获取成功",
            "data": {
                "list": result
            }
        })

    except Exception as e:
        current_app.logger.error(f"获取分享排行榜错误: {str(e)}")
        return jsonify({
            "code": 0,
            "msg": "服务器异常",
            "data": {}
        })


@system_bp.route('/feedback', methods=['POST'])
@jwt_required()
def feedback():
    """用户反馈API接口"""
    try:
        # 获取请求数据
        data = request.json
        if not data:
            return jsonify({"code": 400, "message": "未提供数据"}), 400
        user_id = get_jwt_identity()
        # 必填字段验证
        required_fields = ['content']
        missing_fields = [field for field in required_fields if field not in data or not data[field]]
        if missing_fields:
            return jsonify({"code": 400, "message": f"缺少必填字段: {', '.join(missing_fields)}"}), 400

        # 创建反馈对象并保存到数据库
        feedback = Feedback(
            content=data.get('content', ''),
            contact=data.get('contact', ''),
            status=0,
            user_id=user_id,
            create_time=datetime.datetime.now()
        )
        db.session.add(feedback)
        db.session.commit()
        return jsonify({
            "code": 200,
            "message": "反馈提交成功",
        })
    except Exception as e:
        # 记录错误日志
        current_app.logger.error(f"处理反馈时出错: {str(e)}")
        return jsonify({"code": 500, "message": "服务器内部错误"}), 500


@system_bp.route('/exam/get_questions', methods=['POST'])
def get_exam_questions():
    try:
        from app.services.ocr_engine.data_loader import load_questions_data
        # 加载题目列表
        all_questions = load_questions_data()
        if not all_questions:
            return jsonify({"code": 0, "msg": "题库加载失败"})

        # 根据type_text分类题目
        single_choice_questions = [q for q in all_questions if q.get("type_text") == "单选题"]
        multiple_choice_questions = [q for q in all_questions if q.get("type_text") == "多选题"]
        judge_questions = [q for q in all_questions if q.get("type_text") == "判断题"]

        # 确保题目数量足够
        if len(single_choice_questions) < 10 or len(multiple_choice_questions) < 5 or len(judge_questions) < 5:
            return jsonify({"code": 0, "msg": "题库题目数量不足"})

        # 随机选择10道单选题、5道多选题和5道判断题
        selected_single = random.sample(single_choice_questions, 10)
        selected_multiple = random.sample(multiple_choice_questions, 5)
        selected_judge = random.sample(judge_questions, 5)

        # 合并题目并打乱顺序
        selected_questions = selected_single + selected_multiple + selected_judge
        random.shuffle(selected_questions)

        # 处理题目数据
        exam_questions = []
        for index, question in enumerate(selected_questions, 1):
            question_type = question.get("type_text")
            is_multiple = question_type == "多选题"
            is_judge = question_type == "判断题"

            # 转换答案格式
            answer_map = {
                "1": "A" if not is_judge else "Y",
                "2": "B" if not is_judge else "N",
                "3": "C",
                "4": "D"
            }

            processed_question = {
                "library_id": question.get("library_id", 0),
                "questionId": str(index),
                "questionIndex": index,
                "type": question.get("type", 1),
                "type_text": question_type,
                "subject": question.get("subject", ""),
                "optionA": question.get("optionA", ""),
                "optionB": question.get("optionB", ""),
                "optionC": question.get("optionC", ""),
                "optionD": question.get("optionD", ""),
                "answer": question.get("answer", ""),  # 原始答案格式
                "answerText": answer_map.get(question.get("answer", ""), ""),  # 选项形式的答案
                "solve": question.get("solve", ""),
                "imgUrl": question.get("imgUrl", ""),
                "cart": question.get("cart", ""),
                "state": question.get("state", 10),
                "userAnswer": "" if not is_multiple else [],  # 单选和判断题空字符串，多选题空数组
                "isCorrect": False,
                "isAnswered": False,
                "isJudge": is_judge  # 标记是否为判断题
            }
            exam_questions.append(processed_question)

        return jsonify({
            "code": 1,
            "msg": "获取成功",
            "data": {
                "examId": f"exam_{int(time.time())}",
                "totalQuestions": 20,
                "singleChoiceCount": 10,
                "multipleChoiceCount": 5,
                "judgeCount": 5,
                "passingScore": 90,
                "maxErrors": 2,
                "timeLimit": 45,
                "questions": exam_questions,
            }
        })

    except Exception as e:
        current_app.logger.error(f"获取考试题目错误: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


@system_bp.route('/upload', methods=['POST'])
@token_required
def api_upload_file():
    """处理文件上传API接口"""
    print("接收到文件上传请求")
    return api_upload_file()


@system_bp.route('/search', methods=['POST'])
def _api_search():
    """处理文件上传API接口"""
    print("接收到文件上传请求")
    return api_upload_file()


@system_bp.route('/user/upload_file', methods=['POST'])
def _upload_file_to_cos():
    return upload_file_to_cos()


@system_bp.route('/popup/active', methods=['GET'])
def get_active_popup():
    now = datetime.datetime.now()
    popup = PopupNotice.query.filter(
        PopupNotice.enabled == 1,
        PopupNotice.start_time <= now,
        PopupNotice.end_time >= now
    ).order_by(PopupNotice.start_time.desc()).first()

    if popup:
        return jsonify({
            'code': 1,
            'msg': 'success',
            'data': popup.to_dict()
        })
    else:
        return jsonify({
            'code': 1,
            'msg': '无弹窗信息',
            'data': None
        })


@system_bp.route('/configs/get/<key>', methods=['GET'])
def mp_get_config_by_key(key):
    """小程序专用：根据键名获取单个配置项（无JWT验证）
    
    参数：
        key: 配置键名
    
    返回：
        配置项的值
    """
    try:
        from app.utils.site_config import get_config, SystemConfig
        # 查询配置项
        config_item = db.query.filter_by(config_key=key).first()

        if not config_item:
            return jsonify({
                'code': 0,
                'msg': f'配置项 {key} 不存在'
            }), 404

        # 返回配置值
        return jsonify({
            'code': 1,
            'msg': '获取成功',
            'data': config_item.to_dict()
        })
    except Exception as e:
        current_app.logger.error(f"获取配置项[{key}]失败: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"}), 500


# 获取当前文件（system_api.py）所在目录
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))

# 拼接背景图完整路径
BACKGROUND_IMAGE_PATH = os.path.join(CURRENT_DIR, 'background.jpg')


# 获取小程序 access_token
def get_access_token():
    from app.services.tenant_config_service import get_tenant_config
    tenant_config_service = get_tenant_config().get_wechat_mp_config()
    WX_APP_ID = tenant_config_service.get('app_id')
    WX_APP_SECRET = tenant_config_service.get('app_secret')
    url = f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={WX_APP_ID}&secret={WX_APP_SECRET}'
    res = requests.get(url, verify=False)
    return res.json().get('access_token')


# 获取小程序码
@system_bp.route('/get_qrcode', methods=['GET'])
@jwt_required()
def get_qrcode():
    user_id = get_jwt_identity()  # 取出登录信息，类型是dict
    access_token = get_access_token()
    qr_url = f'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={access_token}'
    payload = {
        "scene": f"sharerId={user_id}",
        "page": "pages/index/index",  # 小程序页面路径
        "width": 430
    }
    print("生成分销", str(payload))
    qr_res = requests.post(qr_url, json=payload)

    if qr_res.headers['Content-Type'] == 'image/jpeg':
        try:
            # 打开背景图并缩小尺寸（例如压缩为宽800）
            bg_img = Image.open(BACKGROUND_IMAGE_PATH).convert("RGBA")
            bg_img = bg_img.resize((800, int(bg_img.height * 800 / bg_img.width)))

            # 打开二维码并缩小尺寸
            qr_img = Image.open(io.BytesIO(qr_res.content)).convert("RGBA")
            qr_img = qr_img.resize((180, 180))  # 可以自定义大小

            # 获取尺寸，计算右下角放置位置
            bg_w, bg_h = bg_img.size
            qr_w, qr_h = qr_img.size
            pos = (bg_w - qr_w - 40, bg_h - qr_h - 160)  # 右下角预留 20px 边距

            # 合成图像
            bg_img.paste(qr_img, pos, qr_img)

            # 转换为 RGB（如果你要保存为 JPEG）
            # final_img = bg_img.convert("RGB")
            final_img = bg_img  # ✅ 保持 RGBA 不转换
            # 保存图片到内存并压缩
            output_buffer = io.BytesIO()
            final_img.save(output_buffer, format='PNG')  # ✅ 不设置 quality
            img_data = output_buffer.getvalue()
            output_buffer.close()

            # base64 编码
            img_base64 = base64.b64encode(img_data).decode()

            return jsonify({
                "code": 0,
                "msg": "success",
                "image": f"data:image/jpeg;base64,{img_base64}"
            })
        except Exception as e:
            return jsonify({"code": 1, "msg": "图片处理失败", "detail": str(e)})

    else:
        return jsonify({"code": 1, "msg": "二维码生成失败", "detail": qr_res.text})


@system_bp.route('/send_email', methods=['GET'])
def send_email():
    try:
        content = request.args.get('content', type=str, default='')  # 获取请求参数
        send_qq_email(content)
        return jsonify({
            "code": 0,
            "msg": "success",
        })
    except Exception as e:
        return jsonify({"code": 1})


def send_qq_email(content):
    try:
        import smtplib
        from email.mime.multipart import MIMEMultipart
        from email.mime.text import MIMEText
        from email.header import Header

        smtp_username = '2380104875@qq.com'
        smtp_password = 'ueztapthhabaeadi'  # 你确认的授权码

        # QQ邮箱SMTP服务器地址
        smtp_server = 'smtp.qq.com'
        smtp_port = 465

        con = smtplib.SMTP_SSL(smtp_server, smtp_port)
        con.login(smtp_username, smtp_password)

        msg = MIMEMultipart()
        msg['From'] = smtp_username
        msg['To'] = smtp_username
        msg['Subject'] = Header('邮件标题', 'utf-8')

        text = MIMEText(content, 'plain', 'utf-8')
        msg.attach(text)

        con.sendmail(smtp_username, smtp_username, msg.as_string())
        con.quit()
        print("邮件发送成功！")
    except Exception as e:
        print(f"邮件发送失败: {e}")





